//
//  main.m
//  CommonProject
//
//  Created by 郝旭珊 on 2017/12/19.
//  Copyright © 2017年 郝旭珊. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

//声明
void demoBlock1();

/*
 1. block 是 C 语言的,调用是c语言的myBlock(); 而不是oc的[self myBlock];
 2. Block 是一个数据类型
 */
int main(int argc, char * argv[]) {
    @autoreleasepool {
        demoBlock1();
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}


void demoBlock3(){
    NSMutableString *strM  = [NSMutableString stringWithString:@"zhangsa"];
    NSLog(@"定义前%@,地址%p",strM,&strM);
    //string 用的是 copy
    
    void (^myBlock)() = ^{
        //setString 只是改变的指针指向地址的内容
        [strM setString:@"lili"];
        //这句话是修改的指针, 这句话是会报错的
//        strM = [NSMutableString stringWithString:@"wangw"];
        
        NSLog(@"in block%@,地址%p",strM,&strM);
    };
    NSLog(@"定义后%@,地址%p",strM,&strM);

    myBlock();
    NSLog(@"%@",strM); //lili

}



void demoBlock2(){
    //使用__ block
    __block int x = 10;
    NSLog(@"定义前: %p",&x); //栈区的地址

    //定义 block 时, 如果引用了__ block, 外部变量的指针地址就会变成堆区的地址,所以能改了
    void (^myBlock)()= ^{
        x = 80;
        NSLog(@"in block: %p",&x); //堆区的地址

    };
    
    myBlock();
    NSLog(@"%d",x); //80
    NSLog(@"定义后: %p",&x); //堆区的地址

}


void demoBlock1(){
    int x = 10; 
    
    NSLog(@"定义前: %p",&x); //栈区的地址
    //定义 block 时, 引用外部变量时,会对外部变量的值做一个 copy
    //后续再改变变量的值, 不会影响 block 内部的值
    //不允许block 内部修改外部变量的值, 因为会破坏代码的可读性, 不易于维护
    //各管个的, 才不乱
    void (^myBlock1)() = ^{
//        x = 80;
        NSLog(@"%d",x);
        NSLog(@"in block%p",&x);//堆区的地址
    };
    x = 20;
    myBlock1();
    NSLog(@"定义后%p",&x); //栈区的地址
    
}


void blockDefine(){
    /*block 定义的速记符号 "inlineblock"
     <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
     <#statements#>
     }; */
    
    /*
     特点:
     1.类型比普通函数多了一个^
     2.设置数值, 有一个^
     3.定义时把 block 当成数据类型(因为=), 执行时当成函数
     */
    
    void(^blockName)() = ^{
        NSLog(@"myBlock");
    };
    
    
    blockName();
    
    //带参数 block
    void (^sumBlock)(int,int) = ^(int x,int y){
        
    };
    
    sumBlock(2,3);
    
    //带返回值block
    int (^sumBlock2)(int,int) = ^int(int a,int b){
        return a+b;
    };
    
    sumBlock2(3,6);
}
